package com.hcy.rabbitruntimeapi.utils;

import com.hcy.rabbitruntimeapi.center.CenterHandlerLink;
import com.hcy.rabbitruntimeapi.center.MessageHandler;
import com.hcy.rabbitruntimeapi.center.MyMessageHandler;
import com.hcy.rabbitbasicmodel.enums.M_Code;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;


import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;

/**
 * @Author huchenying
 * @Description
 * @Date 2021/12/15 19:47
 */
@Component
public class ImportMyMessageHandler  implements ApplicationContextAware{

    Logger logger = LoggerFactory.getLogger(ImportMyMessageHandler.class);

    CenterHandlerLink centerHandlerLink;

    ApplicationContext applicationContext;

    @PostConstruct
    public void init(){
        centerHandlerLink = (CenterHandlerLink) applicationContext.getBean("centerHandlerLink");
        this.run();
    }

    public void run(){
        logger.info("scanner diy annotation start...");

        final String BASE_PACKAGE = "com.hcy.rabbitruntimeapi.center.handler";
        final String RESOURCE_PATTERN = "/*.class";

        //spring工具类，可以获取指定路径下的全部类
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        try {
            String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
            Resource[] resources = resourcePatternResolver.getResources(pattern);
            //MetadataReader 的工厂类
            MetadataReaderFactory readerfactory = new CachingMetadataReaderFactory(resourcePatternResolver);
            for (Resource resource : resources) {
                //用于读取类信息
                MetadataReader reader = readerfactory.getMetadataReader(resource);
                //扫描到的class
                String classname = reader.getClassMetadata().getClassName();
                Class<?> clazz = Class.forName(classname);
                //判断是否有指定主解

                MyMessageHandler anno = clazz.getAnnotation(MyMessageHandler.class);
                if (anno != null) {
                    //将注解中的类型值作为key，对应的类作为 value
                    M_Code value = anno.value();
                    if(value.equals(M_Code.DEFAULT)){
                        throw new RuntimeException(classname + " 上的MyMessageHandler注解value必须要有值!");
                    }
                    String name = clazz.getName();
                    MessageHandler messageHandler = (MessageHandler)applicationContext.getBean(clazz);
                    logger.info("messageHandler scan -> [{}]",classname);
                    centerHandlerLink.addHandler(value.getCode(),messageHandler);
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
